﻿#region Using Statements
using System;
using System.Collections.Generic;//using System.Xml.Serialization;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Net;
#endregion


namespace Pauliver
{
    public class JoinNetworkMenu : BaseMenu
    {
        TerrainSaver ts;
        Texture2D MiniMap;
        Texture2D Minimap_overlay;

        AvailableNetworkSessionCollection avnc;

        int UpdateFrequency = 300;
        int currentUpdate = 0;

        bool CanArrow = false;

        bool ScreenUP = false;

        int networkcount;
        int CurrentGame;
        SpriteFont font;
        string HostName;
        string PlayerCount;
        public JoinNetworkMenu()
            : base()
        {
            //NETWORKING


            font = PContentManager.Instance.GetObject<SpriteFont>(@"Content/Art/Fonts/INVADER");

            networkcount = 0;
            CurrentGame = 0;

            MiniMap = PContentManager.Instance.GetObject<Texture2D>("MiniMap");
            Minimap_overlay = PContentManager.Instance.GetObject<Texture2D>(@"Content/Art/GUI/Minimap_overlay");


            HostName = "Searching....";
            PlayerCount = "";
            
            //create the menu
            _menu = new UIBaseMenu(@"Content/Art/GUI/MenuBackground", Vector2.Zero);

            //Now create buttons
            UIButton b = new UIButton(@"Content/Art/GUI/Join", new Vector2(20, 115));
            _menu.Add(Join, b);

            b = new UIButton(@"Content/Art/GUI/Back", new Vector2(20, 280));
            _menu.Add(Back, b);

            b = new UIButton(@"Content/Art/GUI/Next", new Vector2(219, 194));
            _menu.Add(NextGame, b);

            b = new UIButton(@"Content/Art/GUI/Previous", new Vector2(-20, 194));
            _menu.Add(PreviousGame, b);

            _menu.Setup();

            NetworkManager.Instance.GetAvailableSessions(UpdateCurrent);
        }

        public override void Update(GameTime p_Time)
        {  
            if(++currentUpdate == UpdateFrequency)
            {
                currentUpdate = 0;
                if (avnc != null && !avnc.IsDisposed)
                {
                    avnc.Dispose();
                    avnc = null;
                }
                CanArrow = false;
                NetworkManager.Instance.GetAvailableSessions(UpdateCurrent);
                UpdateCurrent(null);
            }
            _menu.Update();
            _menu.ProcessInput(PlayerIndex.One); //only uncomment me if there are buttons
        }

        protected void UpdateCurrent(AvailableNetworkSessionCollection avn)
        {
            if (ScreenUP) //in case we have moved to a new screen allready
                return;

            avnc = avn;
            if (avn == null || avn.IsDisposed)
            {

                HostName = "Searching....";
                PlayerCount = "";
                CanArrow = false;
                if (avnc != null)
                {
                    avnc.Dispose();
                }
                avnc = null;
                return;
            }
            if (avn.Count == 0)
            {
                HostName = "Searching....";
                PlayerCount = "Players: " + 0;
                CanArrow = false;
                return;
            }

            networkcount = avn.Count;

            if (CurrentGame > networkcount)
                CurrentGame = 0;

            {
                HostName = avn[CurrentGame].HostGamertag;
                PlayerCount = "Players: " + avn[CurrentGame].CurrentGamerCount;
 
                try
                {
                    int MaxPlayers = (int) avn[CurrentGame].SessionProperties[5];
                    int MaxPlayersPerConsole = (int) avn[CurrentGame].SessionProperties[6];
                    int NetCodeRevision = (int) avn[CurrentGame].SessionProperties[7]; //For use Later!

                    if (NetCodeRevision != NetworkManager.NETCODEREVISION)
                    {
                        HostName = "Netcode Rev. = " + NetCodeRevision;
                        PlayerCount= "Should Be [ " + NetworkManager.NETCODEREVISION + " ]" ;
                    }
                    ts = new TerrainSaver();
                    int[] data = new int[9];

                    data[0] = (avn[CurrentGame].SessionProperties[0].Value % 100) - 25; // (oldValues[0] + 25) + ((oldValues[1] + 25) * 100);
                    data[1] = (avn[CurrentGame].SessionProperties[0].Value / 100) - 25; // (oldValues[0] + 25) + ((oldValues[1] + 25) * 100);
                    data[2] = (avn[CurrentGame].SessionProperties[1].Value % 100) - 25; // (oldValues[2] + 25) + ((oldValues[3] + 25) * 100);
                    data[3] = (avn[CurrentGame].SessionProperties[1].Value / 100) - 25; // (oldValues[2] + 25) + ((oldValues[3] + 25) * 100);
                    data[4] = (avn[CurrentGame].SessionProperties[2].Value % 100) - 25; // (oldValues[4] + 25) + ((oldValues[5] + 25) * 100);
                    data[5] = (avn[CurrentGame].SessionProperties[2].Value / 100) - 25; // (oldValues[4] + 25) + ((oldValues[5] + 25) * 100);
                    data[6] = (avn[CurrentGame].SessionProperties[3].Value % 100) - 25; // (oldValues[6] + 25) + ((oldValues[7] + 25) * 100);
                    data[7] = (avn[CurrentGame].SessionProperties[3].Value / 100) - 25; // (oldValues[6] + 25) + ((oldValues[7] + 25) * 100);
                    data[8] = (avn[CurrentGame].SessionProperties[4].Value);

                    ts.Values = data;
                    GenerateTerrain();
                }
                catch (Exception ex)
                {
                    string excetion = ex.ToString();
                    // we should do something, they could be trying to connect to pong
                    // for all we know...
                }
            }
            CanArrow = true;
        }

        public override void ProccessInput(PlayerIndex p_index)
        {
            _menu.ProcessInput(p_index);
        }

        public override void Draw(SpriteBatch p_spriteBatch, GameTime p_Time)
        {
            _menu.Draw(p_spriteBatch, p_Time);
            p_spriteBatch.DrawString(font, HostName, new Vector2(30, 55), Color.White, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, DrawLayer.GetLayer(DrawLayer.LayerDepth.MenuButton));
            p_spriteBatch.Draw(Minimap_overlay, new Vector2(20, 165), null, Color.White, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, DrawLayer.GetLayer(DrawLayer.LayerDepth.MenuButton));
            if (CanArrow)
            {
                p_spriteBatch.DrawString(font, PlayerCount, new Vector2(30, 85), Color.White, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, DrawLayer.GetLayer(DrawLayer.LayerDepth.MenuButton));
                p_spriteBatch.Draw(MiniMap, new Vector2(24, 175), null, Color.White, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, DrawLayer.GetLayer(DrawLayer.LayerDepth.BetweenMenu));
            }
        }

        protected void NextGame()
        {
            if (CanArrow)
            {
                CanArrow = false;
                if (++CurrentGame >= networkcount)
                {
                    CurrentGame = 0;
                }
                UpdateCurrent(avnc);
            }
        }

        protected void PreviousGame()
        {
            if (CanArrow)
            {
                CanArrow = false;
                if (--CurrentGame < 0)
                {
                    CurrentGame = networkcount - 1;
                    if(CurrentGame < 0 )
                    {
                        CurrentGame = 0;
                    }
                }
                UpdateCurrent(avnc);
            }
        }

        protected void Join()
        {
            if (networkcount != 0)
            {
                ScreenUP = true;
                Game1.Instance.PopTopMenu();
                Game1.Instance.AddMenu(new Loading());
                NetworkManager.Instance.Connect(CurrentGame, GameJoined, avnc);
            }
        }

        protected void GameJoined(bool joined)
        {
            if (avnc != null)
            {
                if (!avnc.IsDisposed)
                {
                    avnc.Dispose();
                    avnc = null;
                }
            }
            ScreenUP = true;
            Game1.Instance.PopTopMenu();
            if (joined)
            {
                Game1.Instance.AddMenu(new NetworkLobby(ts, false));
            }
            else
            {
                Game1.Instance.AddMenu(new JoinNetworkMenu());
            }
        }

        public override void Back()
        {
            ScreenUP = true;
            avnc = null;
            Game1.Instance.PopTopMenu();
            System.Threading.Thread.Sleep(10);//hopefully this gives somecleanup time
            Game1.Instance.AddMenu(new NetworkGameMenu() );
        }


        protected void GenerateTerrain()
        {
#if WINDOWS
            GraphicsDevice gd = MiniMap.GraphicsDevice;
            int height = MiniMap.Height;
            int width = MiniMap.Width;
            MiniMap.Dispose();

            MiniMap = new Texture2D(gd, width, height);
            PContentManager.Instance.SaveContent<Texture2D>(MiniMap, "MiniMap");
#endif

            int s_hr = ts.Square_Height;
            int s_wr = ts.Square_Width;
            int t_hr = ts.Triangle_Height;
            int t_wr = ts.Triangle_Width;
            int n1_hr = ts.Noise1_Height;
            int n1_wr = ts.Noise1_Width;
            int n2_hr = ts.Noise2_Height;
            int n2_wr = ts.Noise2_Width;
            int offset = ts.Offset_From_Zero;
            float pi = 3.14159265f;

            int EdgeOffset = Terrain.EdgeOffset;

            Color[] MiniColorData = new Color[MiniMap.Height * MiniMap.Width];
            MiniMap.GetData<Color>(MiniColorData);
            for (int i = (0 + offset + EdgeOffset); i < ((MiniMap.Width * 10) + offset + EdgeOffset); i += 10)
            {
                int square_height = 75 + s_hr, square_width = 10 + s_wr;
                double square = ((square_height) * (Math.Sin((double)0.01 / square_width * 2 * pi * i))) + ((square_height / 3) * (Math.Sin((double)0.01 / square_width * 6 * pi * i))) + ((square_height / 5) * (Math.Sin((double)0.01 / square_width * 10 * pi * i))) + ((square_height / 7) * (Math.Sin((double)0.01 / square_width * 14 * pi * i))) + ((square_height / 9) * (Math.Sin((double)0.01 / square_width * 18 * pi * i)));

                int triangle_height = 100 + t_hr, triangle_width = 8 + t_wr;
                double triangle = (((triangle_height) * (Math.Sin((double)(0.01 / triangle_width) * 2 * pi * i))) - ((triangle_height / 9) * (Math.Sin((double)(0.01 / triangle_width) * 6 * pi * i))) + ((triangle_height / 25) * (Math.Sin((double)(0.01 / triangle_width) * 10 * pi * i))));

                int sine_height = -50 + n1_hr, sine_width = 40 + n1_wr;
                double sine = ((sine_height) * (Math.Sin((double)(0.01 / sine_width) * 2 * pi * i)));

                int noise_height = -25 + n2_hr, noise_width = 20 + n2_wr;
                double noise = ((noise_height) * (Math.Cos((double)(0.1 / noise_width) * 2 * pi * i)));

                double piece6 = 500;
                double temp = square + triangle + sine + noise + piece6;
                for (int j = 0; j < (MiniMap.Height * 10); j += 10)
                {
                    int index = ((i - offset - EdgeOffset) / 10) + (j * MiniMap.Width / 10);
                    if (j > temp)
                    {
                        MiniColorData[index] = Color.Black; //255 means no alpha
                    }
                    else
                    {
                        MiniColorData[index] = new Color(255, 255, 255, 255);
                    }
                }
            }
            MiniMap.SetData<Color>(MiniColorData);
            System.GC.Collect();
        }

 
    }
}
